"""
hg will not clone into an already existing framework.
I understand from reading the internet that there are good reasons for this.

Webfaction and Trigger IO are 2 examples where this is a problem.

Webfaction creates the app before you get a chance to put a repo there.
It also seems to need the apps to be copied into place as linking does not work.
This has something to do with PYTHONPATH (Not investigated).

Trigger IO creates an environment with lots of files and you only need
to change a handfull. It also does not like to create into an existing folder.

This script will either:
    link files from a hg repo into a existing framework or
    copy files into place and fetch them back if changed

e.g.
$ python integratehg.py [-option] ~/Repositories/bodybuilder/ ~/TriggerIO/bodybuilder/
option default is check
check  just looks at differences between repo and framework
link   will link any unlinked repo files in the framework
copy   will copy any uncopied repo files to the framework
fetch  will copy any changed copied files from the framework back to the repo.
existing framework files are never deleted they get renamed to either: oldname.extension.__linked__ or oldname.extension.__copied__
"""

import sys, os

assert sys.platform in ('darwin','linux2'), 'assumes unix commands mv, cp and ln'

validoptions = ['check','link','copy','fetch']

# collect and validate arguments
assert 3<=len(sys.argv)<=4, 'must supply [-option] repo/ framework/'
if len(sys.argv)==3:
    option='check'
    idx = 1
else:
    option = sys.argv[1].lower()
    assert option.startswith('-'), 'option must start with - and contain ' + validoptions
    option = option[1:]
    assert option in validoptions,'options must be one of ' + validoptions
    idx = 2
thehgrepo = sys.argv[idx]
theframework = sys.argv[idx+1]

assert os.path.isdir(thehgrepo), 'repo does not exist ' + thehgrepo
assert thehgrepo.endswith('/'), 'repo must end with/ ' + thehgrepo
assert os.path.isdir(os.path.join(thehgrepo,'.hg')),'no .hg file found in repo ' + thehgrepo
assert os.path.isdir(theframework), 'framework does not exist ' + theframework
assert theframework.endswith('/'), 'framework must end with/ ' + theframework
assert not os.path.isdir(os.path.join(theframework,'.hg')), 'unexpected .hg found in framework'

print '#Repository ', thehgrepo
print '#Framework  ', theframework
print '#Option     ', option

def handle(frameworkfile, repofile):
    """
    """
    frameworkfileexists = os.path.exists(frameworkfile)
    frameworkfileisalink = os.path.islink(frameworkfile)
    frameworkfilecopied = os.path.exists(frameworkfile+'.__copied__')
    frameworkfilelinked = os.path.exists(frameworkfile+'.__linked__')
    if frameworkfileexists:
        filesidentical = open(frameworkfile).readlines() == open(repofile).readlines()
        assert not (frameworkfilecopied and frameworkfilelinked) # this would be bad
    else:
        assert not (frameworkfilecopied or frameworkfilelinked) # this would be bad
    if frameworkfileexists:
        if filesidentical:
            print '#identical  ',
        else:
            print '#differ     ',
        if frameworkfileisalink:
            print '(symlink)',
    else:
        print '#missing    ',
    if frameworkfilecopied:
        print '(__copied__)',
    if frameworkfilelinked:
        print '(__linked__)',
    print repofile
    if option=='check':
        return
    if frameworkfileexists and filesidentical:
        return # nothing to do
    if option=='fetch' and frameworkfileexists and os.path.exists(frameworkfile+'.__copied__'):
        print ('cp %s %s' % (frameworkfile, repofile))
        print ('rm %s.__copied__' % frameworkfile)
        return
    if frameworkfilecopied:
        print '#already copied', frameworkfile
        return
    if frameworkfilelinked:
        print '#already linked', frameworkfile
        return
    if option=='copy':
        if frameworkfileexists:
            print ('mv %s %s.__copied__' % (frameworkfile, frameworkfile))
        print ('cp %s %s' % (repofile, frameworkfile))
    if option=='link':
        if frameworkfileexists:
            print ('mv %s %s.__linked__' % (frameworkfile, frameworkfile))
        print ('ln -s %s %s' % (repofile, frameworkfile))

for root, dirs, files in os.walk(thehgrepo):
    for name in files:
        if name in ('.hgignore', '.hgtags'):
            continue
        repofile = os.path.join(root, name)
        frameworkfile = repofile.replace(thehgrepo, theframework)
        handle(frameworkfile, repofile)
    if '.hg' in dirs:
        dirs.remove('.hg')
